package com.itheima;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Collections;

public class ServerThread extends Thread {

    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        //接收的消息有3种：1.登录消息（包含昵称），2.群聊消息，3.私聊消息
        //所以客户端需声明协议发送消息
        //比如客户端先发1，代表接下来的是登录消息
        //先发2，代表接下来的是群聊消息
        //先发3，代表接下来的是私聊消息
        //先从Socket管道中接收客户端发送来的消息编号
        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            while (true) {
                int type = dis.readInt();
                switch (type) {
                    case 1:
                        //客户端发来了登录消息，接下来要接收昵称数据，再更新全部客户端的在线人数列表
                        String nickname = dis.readUTF();
                        //把这个登录成功的客户端Socket保存到在线集合中
                        Server.onlineSockets.put(socket, nickname);
                        //更新全部客户端的在线人数列表
                        updateClientOnlineUserList();
                        break;

                    case 2:
                        //客户端发来了群聊消息，接下来要接收消息内容，再发送给全部客户端
                        String msg = dis.readUTF();
                        sendMessageToAll(msg);
                        break;

                    case 3:
                        //客户端发来了私聊消息，接下来要接收消息内容，再发送给指定的客户端
                        break;
                }
            }
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("客户端下线了......");
            Server.onlineSockets.remove(socket);        //移除下线的客户端
            updateClientOnlineUserList();       //有用户下线了也需要更新全部客户端的在线人数列表
        }

    }

    private void sendMessageToAll(String msg) {
        //给全部在线Socket管道推送当前客户端发来的消息
        //先拼接昵称、发送时间和消息，拼接格式：昵称 发送时间 消息内容
        StringBuilder sb = new StringBuilder();
        String nickname = Server.onlineSockets.get(socket);

        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss a");
        String sendTime = dtf.format(now);

        String msgResult = sb.append(nickname).append(" ").append(sendTime).append("\r\n").append(msg).append("\r\n").toString();

        //遍历全部在线Socket管道，给每个Socket管道发送消息
        for (Socket socket : Server.onlineSockets.keySet()) {
            try {
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                dos.writeInt(2);        //2代表群聊消息
                dos.writeUTF(msgResult);
                dos.flush();        //刷新
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void updateClientOnlineUserList() {
        //更新全部客户端的在线人数列表
        //拿到全部在线客户端的用户昵称，将这些昵称转发给全部在线的Socket管道
        //1. 拿到全部在线客户端的昵称
        Collection<String> onlineUserNicknames = Server.onlineSockets.values();
        //2. 把这个集合转发给全部在线的Socket管道
        for (Socket socket : Server.onlineSockets.keySet()) {
            try {
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                dos.writeInt(1);        //1代表在线人数消息，2代表群聊消息，3代表私聊消息
                dos.writeInt(onlineUserNicknames.size());       //发送在线人数
                for (String nickname : onlineUserNicknames) {
                    dos.writeUTF(nickname);
                }
                dos.flush();        //刷新
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
